<?php

/**
 * DI注册服务配置文件
 * @category PhalconCMS
 * @copyright Copyright (c) 2016 PhalconCMS team (http://www.marser.cn)
 * @license GNU General Public License 2.0
 * @link www.marser.cn
 */
use Phalcon\DI\FactoryDefault;
use Phalcon\Events\Event;
use Phalcon\Events\Manager as EventsManager;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\View;
use Phalcon\Mvc\Url as UrlProvider;
use Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter;
use Phalcon\Config;
use Phalcon\Db\Profiler as DbProfiler;
use Phalcon\Cache\Frontend\Output as OutputFrontend;
use Phalcon\Cache\Backend\Redis as RedisBackend;
use Phalcon\Mvc\View\Engine\Volt;

//创建一个DIFactory
$di = new FactoryDefault();
//获取所有配置文件
$configData = (require ADMIN_PATH . '/Conf/config.php');



$router = new \Phalcon\Mvc\Router();







/**
 * 把配置文件注册到config对象里面
 */
$di->setShared(
        "config", function () use($configData) {
    return new Config($configData);
}
);

/**
 * 注册调度器
 */
$di->setShared(
        "dispatcher", function () {
    $DefaultAction = "Index";
    $DefaultController = "Index";
// 创建一个事件管理
    $eventsManager = new EventsManager();
// 附上一个侦听者
    $eventsManager->attach(
            "dispatch:beforeDispatchLoop", function (Event $event, $dispatcher) use($DefaultAction, $DefaultController) {
        $params = $dispatcher->getParams();
        if ($dispatcher->getControllerName()) {
            define("__CONTROLLER_NAME__", strtolower($dispatcher->getControllerName()));
        } else {
            define("__CONTROLLER_NAME__", strtolower($DefaultController));
        }
        if ($dispatcher->getActionName()) {
            define("__ACTION_NAME__", strtolower($dispatcher->getActionName()));
        } else {
            define("__ACTION_NAME__", strtolower($DefaultAction));
        }


        getKeyParams($params, $dispatcher);

        $keyParams = [];
        // 用奇数参数作key，用偶数作值
        foreach ($params as $i => $value) {
            if ($i & 1) {
                // Previous param
                $key = $params[$i - 1];

                $keyParams[$key] = $value;
            }
        }

        //添加get参数
        foreach ($_GET as $key => $value) {
            if ($key != '_url') {
                $keyParams[$key] = $value;
            }
        }

        // 重写参数
        $dispatcher->setParams($keyParams);
    });
    $dispatcher = new Dispatcher();
    $dispatcher->setEventsManager($eventsManager);
    $dispatcher->setDefaultNamespace("Admin\Controllers");
    return $dispatcher;
}
);


/**
 * DI注册日志服务
 */
$di->setShared('logger', function() {
    $logger = \Admin\Core\Logger::getInstance(__CONTROLLER_NAME__);
    return $logger;
});

//获取使用路由的url的参数
function getKeyParams(&$params, $dispatcher) {
    $action = $dispatcher->getActionName();
    $routerData = new \Phalcon\Config\Adapter\Php(ADMIN_PATH_CORE . "routers.php");

    if ($action && $params && $routerData) {
        foreach ($routerData->toArray() as $key => $val) {
            if ($val['action'] == $action) {
                $result = [];
                foreach ($params as $k => $v) {
                    $result[] = $k;
                    $result[] = $v;
                }
                break;
            }
        }
        $params = empty($result) ? $params : $result;
    }
}

/**
 * DI注册DB配置 (Shared)单例
 */
$di->setShared('db', function () use($configData, $di) {

    $dbconfig = $configData['shidatuiDB'];


    if (!is_array($dbconfig) || count($dbconfig) == 0) {
        throw new \Exception("the database config is error");
    }

    $connection = new \Phalcon\Db\Adapter\Pdo\Mysql(array(
        "host" => $dbconfig['host'], "port" => $dbconfig['port'],
        "username" => $dbconfig['username'],
        "password" => $dbconfig['password'],
        "dbname" => $dbconfig['dbname'],
        "charset" => $dbconfig['charset'])
    );
    if (APP_DEBUG) {
        $eventsManager = new EventsManager();
        // 分析底层sql性能，并记录日志
        $profiler = new DbProfiler();
        // 监听所有数据库的事件
        $eventsManager->attach('db', function ($event, $connection) use ($profiler, $di) {
            if ($event->getType() == 'beforeQuery') {
                //在sql发送到数据库前启动分析
                $profiler->startProfile($connection->getSQLStatement());
            }
            if ($event->getType() == 'afterQuery') {
                //在sql执行完毕后停止分析
                $profiler->stopProfile();
                //获取分析结果
                $profile = $profiler->getLastProfile();
                $params = $connection->getSqlVariables();
                (is_array($params) && count($params)) && $params = json_encode($params);
                //日志记录
                $logger = $di->getShared("logger");
                $logger->write_log("SQL Statement: " . $profile->getSQLStatement() . "\n" .
                        "Start Time: " . $profile->getInitialTime() . "\n" .
                        "Final Time: " . $profile->getFinalTime() . "\n" .
                        "Total Elapsed Time: " . $profile->getTotalElapsedSeconds() . "\n" .
                        "params:" . "{$params}" . "\n"
                        , 'debug');
            }
        });
        $connection->setEventsManager($eventsManager);
    }
    return $connection;
});

// Register Volt as a service
$di->setShared(
        "voltService", function ($view, $di) {
    $volt = new Volt($view, $di);

    $volt->setOptions(
            [
                "compiledPath" => VOLT,
                "compiledExtension" => ".compiled",
            ]
    );

    //自定义过滤器
    $compiler = $volt->getCompiler();
    $compiler->addFilter('cutStr', function($resolvedArgs, $exprArgs) {
        return 'cut_str(' . $resolvedArgs . ',20)';
    });

    return $volt;
}
);

// 设置视图组件
$di->setShared(
        "view", function () {
    $view = new View();

    $view->setViewsDir(ADMIN_PATH . "Views/");

    $view->registerEngines(
            [
                ".volt" => "voltService",
                ".phtml" => "voltService",
            ]
    );

    return $view;
}
);

// 设置公共视图组件
$di->setShared(
        "commonView", function () {
    $view = new View();

    $view->setViewsDir(PLATFORM . "/Views/");

    $view->registerEngines(
            [
                ".volt" => "voltService",
                ".phtml" => "voltService",
            ]
    );
    return $view;
}
);




// 设置一个基础URI, 这样所有生成的URI都包含"tutorial"文件夹
$di->setShared(
        "url", function () {
    $url = new UrlProvider();

    $url->setBaseUri("/");

    return $url;
}
);

/**
 * DI注册缓存服务
 */
//$di->setShared('redisCache', function() use($configData) {
//    $cacheconfig = $configData['DEFAULT_REDIS_CONFIG'];
//    return \Platform\Libs\RedisCache::getInstance($cacheconfig['host'], $cacheconfig['port'], $cacheconfig['timeout'], $cacheconfig['auth']);
//});




/**
 * 使用file元数据模型缓存数据库表结构
 */
$di->setShared("modelsMetadata", function () {
    if (!file_exists(CACHE . 'Metadata/')) {
        mkdir(CACHE . 'Metadata/');
    }
    $metaData = new \Phalcon\Mvc\Model\Metadata\Files(array(
        'metaDataDir' => CACHE . 'Metadata/'
    ));
    return $metaData;
});





/**
 * 设置路由
 */
$di->setShared('router', function() {
    $router = new \Phalcon\Mvc\Router();
//            $router->setDefaultModule('frontend');
    $routerRules = new \Phalcon\Config\Adapter\Php(ADMIN_PATH_CORE . "routers.php");
    foreach ($routerRules->toArray() as $key => $value) {
        $router->add($key, $value);
    }

    return $router;
});

/**
 * DI注册缓存服务
 */
$di->setShared('fileCache', function() {
    if (!file_exists(HTML_PATH . date('Y-m', time()))) {
        mkdir(HTML_PATH . date('Y-m', time()));
    }
    return new \Phalcon\Cache\Backend\File(new \Phalcon\Cache\Frontend\Output(), array(
        'cacheDir' => HTML_PATH . date('Y-m', time()) . "/"
    ));
});

/**
 * DI注册mongodb
 */
//$di->setShared("mongoCache", function() {
//    return \Platform\Libs\MongoDBCache::getInstance();
//});

/**
 * DI注册session服务
 */
$di->setShared('session', function() {
    $session = new Phalcon\Session\Adapter\Files();
    $session->start();
    return $session;
});


/**
 * DI注册缓存服务
 */
$di->setShared('redisCache', function() use($configData) {
    $cacheconfig = $configData['DEFAULT_REDIS_CONFIG'];
    return \Platform\Libs\RedisCache::getInstance($cacheconfig['host'], $cacheconfig['port'], $cacheconfig['timeout'], $cacheconfig['auth'], $cacheconfig['dbnumber']);
});

